package cn.net.shuxing.yifu.common.service;

import cn.net.shuxing.yifu.common.bean.BaseBean;
import cn.net.shuxing.yifu.common.util.CommonExample;
import cn.net.shuxing.yifu.common.util.TimeExample;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public abstract class BaseService<B extends BaseBean, M extends Mapper<B>> {

    @Autowired
    protected M mapper;

    public B getByPrimaryKey(Object key) {
        B bean = mapper.selectByPrimaryKey(key);
        if (bean == null)
            return null;
        if (bean.getDeleted() == 1)
            return null;
        complete(bean);
        return bean;
    }

    public B getByPrimaryKeyWithoutComplete(Object key) {
        B bean = mapper.selectByPrimaryKey(key);
        if (bean == null)
            return null;
        if (bean.getDeleted() == 1)
            return null;
        return bean;
    }

    public B get(B bean) {
        bean.setDeleted(0);
        bean = mapper.selectOne(bean);
        if (bean == null)
            return null;
        complete(bean);
        return bean;
    }

    public B getWithoutComplete(B bean) {
        bean.setDeleted(0);
        bean = mapper.selectOne(bean);
        if (bean == null)
            return null;
        return bean;
    }

    public List<B> gets(B bean) {
        bean.setDeleted(0);
        List<B> beans = mapper.select(bean);
        if (beans == null)
            return null;
        completeAll(beans);
        return beans;
    }

    public List<B> getsWithoutComplete(B bean) {
        bean.setDeleted(0);
        List<B> beans = mapper.select(bean);
        if (beans == null)
            return null;
        return beans;
    }


    /**
     * @param paramMap 键位数据库表的字段名，用下划线式
     * @return
     */
    public List<B> gets(Map<String, Object> paramMap) {
        TimeExample example = new TimeExample(getBeanClass());
        example.equals("deleted", 0);
        Set<String> fieldNameSet = paramMap.keySet();
        for (String fieldName : fieldNameSet) {
            example.equals(fieldName, paramMap.get(paramMap));
        }
        List<B> beanList = mapper.selectByExample(example);
        if (beanList == null)
            return null;
        completeAll(beanList);
        return beanList;

    }

    public List<B> getsWithoutComplete(Map<String, Object> paramMap) {
        TimeExample example = new TimeExample(getBeanClass());
        example.equals("deleted", 0);
        Set<String> fieldNameSet = paramMap.keySet();
        for (String fieldName : fieldNameSet) {
            example.equals(fieldName, paramMap.get(paramMap));
        }
        List<B> beanList = mapper.selectByExample(example);
        if (beanList == null)
            return null;
        return beanList;

    }

    public List<B> getAll() {
        CommonExample example = new CommonExample(getBeanClass());
        example.equals("deleted", 0);
        List<B> beans = mapper.selectByExample(example);
        if (beans == null)
            return null;
        completeAll(beans);
        return beans;
    }

    public List<B> getAllWithoutComplete() {
        CommonExample example = new CommonExample(getBeanClass());
        example.equals("deleted", 0);
        List<B> beans = mapper.selectByExample(example);
        if (beans == null)
            return null;
        return beans;
    }

    protected void complete(B bean) {

    }

    protected void completeAll(Collection<B> beans) {
        if (beans == null || beans.isEmpty())
            return;
//        beans.stream().forEach(this::complete);
        for (B bean : beans) {
            complete(bean);
        }
    }

    protected Class<B> getBeanClass() {
        try {
            String name = this.getClass().getName();
            String className = name.substring(name.lastIndexOf("."), name.lastIndexOf("Service"));
            String packageName = name.substring(0, name.lastIndexOf("."));
            packageName = packageName.substring(0, packageName.lastIndexOf("."));
            packageName += ".bean";
            className = packageName + className;
            Class<B> beanClass = (Class<B>) Class.forName(className);
            return beanClass;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected B createBeanObject() {
        try {
            return getBeanClass().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public int insert(B bean) {
        return mapper.insertSelective(bean);
    }

    public int update(B bean) {
        bean.resetUpdateTime();
        return mapper.updateByPrimaryKeySelective(bean);
    }

    public boolean delete(Object primaryKey) {
        B bean = getByPrimaryKey(primaryKey);
        if (bean != null) {
            bean.setDeleted(1);
            update(bean);
        }
        return true;
    }

    protected List<B> getsByExample(Example example) {
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deleted", 0);
        example.and(criteria);
        List<B> beans = mapper.selectByExample(example);
        completeAll(beans);
        return beans;
    }

    protected B getByExample(Example example) {
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deleted", 0);
        example.and(criteria);
        B bean = mapper.selectOneByExample(example);
        complete(bean);
        return bean;
    }

    protected List<B> getsByExampleWithoutComplete(Example example) {
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deleted", 0);
        example.and(criteria);
        List<B> beans = mapper.selectByExample(example);
        return beans;
    }

    protected B getByExampleWithoutComplete(Example example) {
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deleted", 0);
        example.and(criteria);
        B bean = mapper.selectOneByExample(example);
        return bean;
    }


}
